﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Net;
using System.Xml;
using StripeOne.Core.S1Tools;
using StripeOne.Core.S1Cache;

namespace StripeOne.Core.XmlConfig
{
	public class XmlObjectTool : XmlTool
	{

		#region ConvertXmlObject
		private static T ConvertXmlObject<T>(object objCache) where T : XmlObject
		{
			try
			{
				return (T)objCache;
			}
			catch
			{
				return null;
			}
		}
        private static List<T> ConvertXmlObjects<T>(object objCache) where T : XmlObject
		{
			try
			{
				return (List<T>)objCache;
			}
			catch{
				return null;
			}
		}
		#endregion

		#region GetXmlObjectsNoCache
		private static T GetXmlObjectNoCache<T>(XmlElement xmlDoc, string section) where T : XmlObject
		{
			T objResult = ParseXmlObject<T>(xmlDoc, section);
			if(objResult == null)
			{
				objResult = CreateXmlObject<T>(section);
				objResult.XmlElement = xmlDoc;
				section = section.Split('/').Length > 0 ? section.Split('/').Max() : section;
				objResult.Section = section;
			}
			return objResult;
		}
		private static List<T> GetXmlObjectsNoCache<T>(XmlElement xmlDoc, string section, string path) where T : XmlObject
		{
			List<T> objResult = ParseXmlObjects<T>(xmlDoc, section, path);
			objResult = objResult == null ? new List<T>() : objResult;
			return objResult;
		}
		#endregion

		#region GetXmlObjects [Parsed]

		// GetObjectXml
		public static T GetXmlObject<T>(string feedUrl, string section, string keyCache, int cacheKey) where T : XmlObject
		{
			return GetXmlObject<T>(GetXmlElement(feedUrl, section,  cacheKey), section);
		}
		public static T GetXmlObject<T>(string feedUrl, string section, bool isLocalFile, string keyCache, int cacheKey) where T : XmlObject
		{
			return GetXmlObject<T>(GetXmlElement(feedUrl, section, isLocalFile,  cacheKey), section);
		}
		public static T GetXmlObject<T>(XmlDocument xmlDoc, string section) where T : XmlObject
		{
			if(xmlDoc == null) return CreateXmlObject<T>(section);
			return GetXmlObject<T>(xmlDoc.DocumentElement, section);
		}
		public static T GetXmlObject<T>(XmlElement xmlElement) where T : XmlObject
		{
			if(xmlElement == null) return CreateXmlObject<T>("");
			return GetXmlObject<T>(xmlElement, xmlElement.Name);
		}
		public static T GetXmlObject<T>(XmlElement xmlElement, string section) where T : XmlObject
		{
			T objResult = GetXmlObjectNoCache<T>(xmlElement, section);
			return objResult;
		}

		// GetObjectsXml
		public static List<T> GetXmlObjects<T>(string feedUrl, string section, string path, int cacheKey) where T : XmlObject
		{
			return GetXmlObjects<T>(GetXmlElement(feedUrl, section, cacheKey), String.Empty, path);
		}
		public static List<T> GetXmlObjects<T>(string feedUrl, string section, string path, bool isLocalFile,int cacheKey) where T : XmlObject
		{
			return GetXmlObjects<T>(GetXmlElement(feedUrl, section, isLocalFile, cacheKey), String.Empty, path);
		}
		public static List<T> GetXmlObjects<T>(XmlDocument xmlDoc, string section, string path) where T : XmlObject
		{
			if(xmlDoc == null) return new List<T>();
			return GetXmlObjects<T>(xmlDoc.DocumentElement, section, path);
		}
		public static List<T> GetXmlObjects<T>(XmlElement xmlElement, string section, string path) where T : XmlObject
		{
			List<T> objResult = GetXmlObjectsNoCache<T>(xmlElement, section, path);
			return objResult;
		}

		#endregion

		#region ParseXmlObjects [Parsed]

		// ParseObjectXml
		private static T ParseXmlObject<T>(XmlElement xmlDoc, string section) where T : XmlObject
		{
			T obj = null;

			if(xmlDoc == null) return obj;

			XmlNode xmlNode = GetXmlNode(xmlDoc, section, false);

			if(xmlNode != null)
			{
				obj = CreateXmlObject<T>(section);
				if(obj == null) return null;

				obj.XmlElement = (XmlElement)xmlNode;
				obj.Section = obj.XmlElement.Name;
			}
			return obj;
		}

		// ParseObjectsXml
		private static List<T> ParseXmlObjects<T>(XmlElement xmlDoc, string section, string path) where T : XmlObject
		{
			List<T> objects = null;
			if(xmlDoc == null) return objects;

			XmlNodeList xmlNodeList;

			if(section != String.Empty)
			{
				xmlNodeList = GetXmlNodeList(GetXmlElement(xmlDoc, section), path, false);
			}
			else
			{
				xmlNodeList = GetXmlNodeList(xmlDoc, path, false);
			}

			if(xmlNodeList != null)
			{
				objects = new List<T>();
				foreach(XmlElement item in xmlNodeList)
				{
					T obj = CreateXmlObject<T>(path);
					if(obj == null) continue;

					obj.XmlElement = item;
					obj.Section = obj.XmlElement.Name;

					objects.Add((T)obj);
				}
			}
			return objects;
		}

		#endregion

		#region CreateXmlObject ConstructorInfo [Parsed]

		public static T CreateXmlObject<T>() where T : XmlObject
		{
			try
			{
				return S1Reflection.GetInstance<T>();
			}
			catch
			{
				return null;
			}
		}
		public static T CreateXmlObject<T>(string mediaType) where T : XmlObject
		{
			try
			{
				return S1Reflection.GetInstance<T>(new Type[] { typeof(string) }, new object[] { mediaType });
			}
			catch
			{
				return CreateXmlObject<T>();
			}
		}
		public static T CreateXmlObject<T>(object[] parameters) where T : XmlObject
		{
			try
			{
				Type[] types = new Type[parameters.Length];
				int i = 0;
				foreach(object param in parameters)
				{
					types[i] = param.GetType();
					i++;
				}

				return S1Reflection.GetInstance<T>(types, parameters);
			}
			catch
			{
				return null;
			}
		}
		#endregion

	}
}